package com.tvunetworks.center.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.model.dto.CheckAuthDTO;
import com.tvunetworks.center.common.model.dto.instance.ApiParam;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.device.constant.DeviceApiConstant;
import com.tvunetworks.center.device.mapper.DeviceGeoMapper;
import com.tvunetworks.center.device.model.api.*;
import com.tvunetworks.center.device.service.DeviceGeoApiService;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.feign.AccessFeignService;
import com.tvunetworks.center.device.service.feign.UserFeignService;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
/**
 * @program: tvucc-aggregator
 * @author lebronchen
 * @create: 2020-03-13 08:10
 **/
@Service
@Slf4j
public class DeviceGeoApiServiceImpl implements DeviceGeoApiService {
    @Autowired
    private UserFeignService userFeignService;
    @Autowired
    private DeviceGeoMapper deviceGeoMapper;
    @Autowired
    @Qualifier("ccMemcacheClient")
    private MemcachedClient ccMemcachedClient;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DevicePairService devicePairService;
    @Autowired
    private AccessFeignService accessFeignService;

    @Override
    public ResponseStructure<DeviceGeoStructure> getDeviceGeoInfoListXml(String xml, String ip) throws Exception {
        ResponseStructure<DeviceGeoStructure> resultXml =  new ResponseStructure<DeviceGeoStructure>();

        //解析xml
        String appkey = "";
        String timestamp = "";
        String signature = "";
//        String data = "";
        String session = "";
        String rid = "";
        StringReader sr = new StringReader(xml);
        InputSource is = new InputSource(sr);
        SAXReader reader = new SAXReader();
        org.dom4j.Document document = reader.read(is);
                //get root Node
        Element root = document.getRootElement();
        if (root.content().size() != 0) {
            Element appkeyEl = root.element("Appkey");
            Element timestampEl = root.element("Timestamp");
            Element signatureEl = root.element("Signature");
            Element sessionEl = root.element("Session");
            Element ridEl = root.element("Rid");
            if(appkeyEl !=null){
                appkey = appkeyEl.getStringValue();
            }
            if(timestampEl !=null){
                timestamp = timestampEl.getStringValue();
            }
            if(signatureEl !=null){
                signature = signatureEl.getStringValue();
            }
            if(sessionEl !=null){
                session = sessionEl.getStringValue();
            }
            if(ridEl !=null){
                rid = ridEl.getStringValue();
            }
        }
        if (StringUtils.isEmpty(appkey) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(signature)
                || StringUtils.isEmpty(session)) {
            return resultXml.setResult(DeviceGeoResponse.PARAMETER_ERROR);
        }

        // check authenticate
        DeviceGeoApiParam deviceGeoApiParam = new DeviceGeoApiParam();
        deviceGeoApiParam.setAppkey(appkey);
        deviceGeoApiParam.setTimestamp(timestamp);
        deviceGeoApiParam.setSignature(signature);
        deviceGeoApiParam.setIp(ip);
        Result<Void> checkAuthResult = checkAuth(deviceGeoApiParam);
        if (!checkAuthResult.assertSuccess()) {
            resultXml.setErrorCode(checkAuthResult.getErrorCode());
            resultXml.setErrorInfo(checkAuthResult.getErrorInfo());
            return resultXml;
        }

        // check user
        Result<LoginUser> loginUser = userFeignService.getLoginUser( session);
        String userId = "";
        if(loginUser !=null){
            userId = loginUser.getResult().getId();
        }
        if (StringUtils.isEmpty(userId)) {
            return resultXml.setResult(DeviceGeoResponse.NO_LOGIN);
        }
        //check Rid belong to current user
        boolean isCurrentR = checkCurrentR(userId,rid);
        if(!isCurrentR){
            return resultXml.setResult(DeviceGeoResponse.CHECK_IS_CURRENT_R);
        }
        List<DeviceGeoRemoteInfo> list = getDeviceGeoInfoByRid(rid,userId);
        DeviceGeoStructure ds = new DeviceGeoStructure(list);
        resultXml.setData(ds);
        resultXml.setResult(DeviceGeoResponse.SUCCESS);
        return resultXml;
    }

    /**
     *
     * @param userid userid
     * @param rid rid
     * @return boolean
     * @throws Exception 编译异常
     */
    //check rid is not belong to current user
    public boolean checkCurrentR(String userid,String rid) throws Exception{
        boolean flag = true;
        List<String> rList = deviceGeoMapper.listRId(userid,rid);
        if(rList.size()==0){
            flag=false;
        }
        return flag;
    }

    /**
     *
     * @param rid rid
     * @param userId userId
     * @return List
     * @throws Exception 编译异常
     */
    public List<DeviceGeoRemoteInfo> getDeviceGeoInfoByRid(String rid,String userId) throws Exception{
        List<DeviceGeoRemoteInfo> deviceGeoRemoteInfoList = new ArrayList<DeviceGeoRemoteInfo>();
    //    List<String> userPeerIds = listCacheDevicePeerId(userId);
        //get pair List Tid
        List<String> packIdList = devicePairService.listRPairT(rid);
        List<String> gridIdList = devicePairService.listRPairX(rid);
        List<String> allPeerIdList = new ArrayList<String>();
        if ( packIdList != null && packIdList.size() > 0 ) {
            allPeerIdList.addAll(packIdList);
        }
        if ( gridIdList != null && gridIdList.size() > 0 ) {
            allPeerIdList.addAll(gridIdList);
        }
        //filter peerId not bind with user
  //      allPeerIdList.retainAll(userPeerIds);
        //get DeviceGeoInfo By Device id
        if(allPeerIdList ==null || allPeerIdList.size()==0){
            return deviceGeoRemoteInfoList;
        }
        String peerIdStr = StringUtils.join(allPeerIdList, "_");
        Result<String> geoStr = deviceService.listGPSByMultiPeerId(peerIdStr);
        deviceGeoRemoteInfoList = JSON.parseArray(geoStr.getResult(),DeviceGeoRemoteInfo.class);
       // geoStr.getResult();
        return deviceGeoRemoteInfoList;
    }

    /**
     *
     * @param userId userId
     * @return List
     */
    public List<String> listCacheDevicePeerId(String userId) {
        try {
            List<String> peerIdList = (List<String>)ccMemcachedClient.get(DeviceApiConstant.USER_DEVICE_PEERID + userId);
            if ( peerIdList != null && peerIdList.size() > 0 ) {
                return peerIdList;
            }
        } catch (Exception e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
            log.error(e.getMessage(),e);
        }
        List<String> peerIdList = deviceGeoMapper.listPeerIds(userId);
        try {
            if ( peerIdList != null && peerIdList.size() > 0 ) {
                ccMemcachedClient.set(DeviceApiConstant.USER_DEVICE_PEERID + userId, 0,peerIdList);
            }
        } catch (Exception e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
            log.error(e.getMessage(),e);
        }
        return peerIdList;
    }
    @Override
    public DeviceGeoResult<List<DeviceGeoRemoteInfo>> getDeviceGeoInfoListJson(JSONObject jsonObject, String ip) throws Exception {
        // check parameter
        DeviceGeoResult<List<DeviceGeoRemoteInfo>> result = new DeviceGeoResult<List<DeviceGeoRemoteInfo>>();
        String appkey = null;
        String timestamp = null;
        String signature = null;
        String session = null;
        String rid = null;
        try {
            appkey = jsonObject.getString("appkey");
            timestamp = jsonObject.getString("timestamp");
            signature = jsonObject.getString("signature");
            session = jsonObject.getString("session");
            rid = jsonObject.getString("rid");
        } catch (Exception e) {

            log.error("Receiver Geo API parameter error:" + jsonObject.toString(), e);
            return result.setResult(DeviceGeoResponse.PARAMETER_ERROR);
        }

        if (StringUtils.isEmpty(appkey) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(signature)
                || StringUtils.isEmpty(session)) {
            return result.setResult(DeviceGeoResponse.PARAMETER_ERROR);
        }
        // check user
        // check user
        Result<LoginUser> loginUser = userFeignService.getLoginUser( session);
        String userId = "";
        if(loginUser !=null){
            userId = loginUser.getResult().getId();
        }
        if (StringUtils.isEmpty(userId)) {
            return result.setResult(DeviceGeoResponse.NO_LOGIN);
        }
        //check Rid belong to current user
        boolean isCurrentR = checkCurrentR(userId,rid);
        if(!isCurrentR){
            return result.setResult(DeviceGeoResponse.CHECK_IS_CURRENT_R);
        }
        List<DeviceGeoRemoteInfo> list = getDeviceGeoInfoByRid(rid,userId);
        result.setContent(list);
        result.setResult(DeviceGeoResponse.SUCCESS);
        return result;
    }
    private Result<Void> checkAuth(ApiParam apiParam) {

        CheckAuthDTO checkAuthDTO = apiParam.convertToCheckAuto();
        checkAuthDTO.setFunction("default");
        try {
            return accessFeignService.checkAuth(checkAuthDTO);
        } catch (Exception e) {
            log.error("checkAuth exception", e);
            return ResultUtil.error("80050026", e.getMessage());
        }
    }

}
